package task

import (
	"errors"
	"github.com/gin-gonic/gin"
	log "github.com/sirupsen/logrus"
	"oa-rest/common"
	"oa-rest/models/message"
	"oa-rest/models/user"
	"time"
	"xorm.io/xorm"
)

func (t *Task) SavTask(c *gin.Context) error {
	_, err := common.DB.Transaction(func(session *xorm.Session) (interface{}, error) {
		userName := c.GetString("username")
		realName := c.GetString("realName")

		t.Status = 1
		t.Operator = userName
		t.OperatorName = realName

		if _, err := session.Insert(t); err != nil {
			log.Printf("Create %s failed: %v", "task", err)
			return nil, err
		}

		// 从参数里拆分出node信息和node item信息，保存到数据库
		// 添加第一个node，也就是申请人
		firstNodeTime := time.Now().Format("2006-01-02 15:04:05")
		firstNode := &TaskNode{
			TaskId:  t.Id,
			Name:    "申请人",
			Status:  2,
			Pid:     0,
			EndTime: firstNodeTime,
			ItemList: []*TaskNodeItem{{
				Username:    userName,
				RealName:    realName,
				Status:      2,
				TaskId:      t.Id,
				ApproveTime: firstNodeTime,
			}},
		}

		t.NodeList = append([]*TaskNode{firstNode}, t.NodeList...)

		pid := int64(0)
		for i, node := range t.NodeList {
			tempNode := &TaskNode{
				TaskId: t.Id,
				Name:   node.Name,
				Status: getNodeStatus(t.SubType, i),
				Pid:    pid,
			}
			_, err := session.Insert(tempNode)
			if err != nil {
				log.Printf("Create %s failed: %v", "task", err)
				return nil, err
			}
			pid = tempNode.Id
			items := make([]*TaskNodeItem, 0)
			for _, item := range node.ItemList {
				tempItem := &TaskNodeItem{
					NodeId:   tempNode.Id,
					Username: item.Username,
					RealName: item.RealName,
					Status:   getItemStatus(item.Status),
					TaskId:   t.Id,
				}
				items = append(items, tempItem)
			}
			_, err = session.Insert(items)
			if err != nil {
				log.Printf("Create %s failed: %v", "task", err)
				return nil, err
			}
		}
		return nil, nil
	})
	if err != nil {
		log.Printf("事务执行失败: %v", err)
	}

	return err
}

// 批准
func (p *approveParam) saveFlag1() error {
	_, err := common.DB.Transaction(func(session *xorm.Session) (interface{}, error) {
		currentTime := time.Now().Format("2006-01-02 15:04:05")
		// 1.保存item的信息（reason+approveTime）
		_, err := session.Exec("update task_node_item set reason = ?, approve_time=?,status=2 where id = ?", p.Item.Reason, currentTime, p.Item.Id)
		if err != nil {
			return nil, err
		}

		var tk Task
		if _, err = session.SQL("select * from task where id = ?", p.TaskId).Get(&tk); err != nil {
			return nil, err
		}
		// 2.1.获取该节点是否还有其他未完成的item，没有，则该节点结束；有，就忽略。
		var count int64
		gotoNext := false
		if _, err = session.SQL("select count(1) from task_node_item where node_id = ? and status=1", p.NodeId).Get(&count); err != nil {
			return nil, err
		}
		if count == 0 {
			// 2.2.没有，则该node结束
			if _, err = session.Exec("update task_node set status = 3, end_time=? where id = ?", currentTime, p.NodeId); err != nil {
				return nil, err
			}
			gotoNext = true
			log.Warn("=========gotonext---1111")
		}

		if gotoNext {
			// 3.还需要判定是否存在下一节点，然后判断流程结束还是流转到下一节点
			nextNodeId := 0
			_, err = session.SQL("select id from task_node where pid=?", p.NodeId).Get(&nextNodeId)
			if err != nil {
				return nil, err
			}

			if nextNodeId > 0 {
				log.Warn("======111===get===")
				// 3.1.找到下一节点，就修改下一节点的状态
				_, err = session.Exec("update task_node set status = 2 where pid = ?", p.NodeId)
				if err != nil {
					return nil, err
				}
				// 3.1.1.同时清空item下的所有审批状态（就是二次审批）
				_, err = session.Exec("update task_node_item set status = 1,reason='',approve_time='' where node_id = ?", nextNodeId)
				if err != nil {
					return nil, err
				}
			} else {
				log.Warn("=====222====no get===")
				// 3.2.找不到下一节点，就表示当前节点就是最后一个节点，流程结束，自动归档。
				_, err = session.Exec("update task set status = 2 where id = ?", p.TaskId)
				if err != nil {
					return nil, err
				}

				// 3.3.流程正常结束，给发起人发送重要通知
				msg := message.Message{
					RefName:  tk.Title,
					Receiver: tk.Operator,
					Status:   1,
					Type:     3,
					RefId:    p.TaskId,
					Priority: 1,
					Sender:   "系统",
				}
				if _, err = session.Insert(&msg); err != nil {
					return nil, err
				}
			}
		}

		return nil, nil
	})
	return err
}

// 驳回
// todo 无层级的暂不支持驳回
func (p *approveParam) saveFlag2() error {
	_, err := common.DB.Transaction(func(session *xorm.Session) (interface{}, error) {
		currentTime := time.Now().Format("2006-01-02 15:04:05")
		var tk Task
		if _, err := session.SQL("select * from task where id = ?", p.TaskId).Get(&tk); err != nil {
			return nil, err
		}
		// 1.保存item的信息（reason+approveTime）
		// todo 目前先直接覆盖，后期看是否支持（驳回-再批这种全流程都记录的）
		if _, err := session.Exec("update task_node_item set reason = ?, approve_time=?,status=3 where id = ?", p.Item.Reason, currentTime, p.Item.Id); err != nil {
			return nil, err
		}

		var pid int64
		isClose := false
		if _, err := session.SQL("select pid from task_node where id=?", p.NodeId).Get(&pid); err != nil {
			return nil, err
		}

		if pid == 0 { // 2.1.如果是第一级节点，流程直接结束 todo 新需求，需要回退，然后申请人需要修改后，重新提交
			// todo 1.回退本级
			// todo 2.将task设置一个状态，表示需要重新修改

			isClose = true
		} else {                // 2.2.如果不是，根据subFlag
			if p.SubFlag == 1 { //还原本节点状态，回退上级节点状态
				if _, err := session.Exec("update task_node set status = 1, end_time=? where id = ?", currentTime, p.NodeId); err != nil {
					return nil, err
				}
				if _, err := session.Exec("update task_node set status = 2 where id = ?", pid); err != nil {
					return nil, err
				}
				//上级节点的item都要重置
				if _, err := session.Exec("update task_node_item set status = 1,reason='',comment='',approve_time='' where node_id= ?", pid); err != nil {
					return nil, err
				}

				// 流程未结束，但被驳回
				msg := message.Message{
					RefName:  tk.Title,
					Receiver: tk.Operator,
					Status:   1,
					Type:     4,
					RefId:    p.TaskId,
					Priority: 2,
					Sender:   p.Item.Name,
				}
				if _, err := session.Insert(&msg); err != nil {
					return nil, err
				}
			} else { // 流程结束
				isClose = true
			}
		}
		if isClose {
			// 3.2.流程结束，自动归档。
			if _, err := session.Exec("update task set status = 3 where id = ?", p.TaskId); err != nil {
				return nil, err
			}
			// 3.3.流程异常结束，给发起人发送重要通知
			msg := message.Message{
				RefName:  tk.Title,
				Receiver: tk.Operator,
				Status:   1,
				Type:     4,
				RefId:    p.TaskId,
				Priority: 2,
				Sender:   "系统",
			}
			if _, err := session.Insert(&msg); err != nil {
				return nil, err
			}

		}
		return nil, nil
	})
	return err
}

// 批注
func (p *approveParam) saveFlag3(c *gin.Context) error {
	_, err := common.DB.Transaction(func(session *xorm.Session) (interface{}, error) {
		userName := c.GetString("username")
		if userName == "" {
			return nil, errors.New("no auth")
		}
		var currenUser user.UsUser

		get, err := session.SQL("select * from us_user where user_name = ? limit 1", userName).Get(&currenUser)
		if !get || err != nil {
			return nil, err
		}

		var tkComment TaskComment
		get, err = session.SQL("select * from task_comment where task_id = ? and user_name = ? limit 1", p.TaskId, currenUser.UserName).Get(&tkComment)
		if err != nil {
			return nil, err
		}

		if get { // 2.1.有记录更新
			tkComment.Comment = p.Item.Comment
			tkComment.SignatureUrl = currenUser.SignUrl
			_, err = session.ID(tkComment.Id).Cols("comment", "signature_url").Update(&tkComment)
			if err != nil {
				return nil, err
			}
		} else { // 2.2.没有记录则新建
			tkComment.TaskId = p.TaskId
			tkComment.Comment = p.Item.Comment
			tkComment.UserName = userName
			tkComment.RealName = currenUser.RealName
			tkComment.SignatureUrl = currenUser.SignUrl

			_, err = session.Insert(&tkComment)
			if err != nil {
				return nil, err
			}
		}
		return nil, nil
	})
	if err != nil {
		log.Printf("session failed: %v", err)
	}
	return err
}

func getNodeStatus(subType int64, index int) int64 {
	// 无层级，都是2（激活）
	if subType == 2 {
		return 2
	}
	// 有层级，第1个node是3 ,第2个node是2
	if subType == 1 {
		if index == 0 {
			return 3
		}
		if index == 1 {
			return 2
		}
	}
	return 1
}

func getItemStatus(status int64) int64 {
	if status == 0 {
		return 1
	}
	return status
}

func getTaskTemplateNodeList(templateId int64) ([]*TaskTemplateNode, error) {
	// 查询模板节点列表
	var nodes []*TaskTemplateNode
	if err := common.DB.Where("template_id = ?", templateId).Asc("id").Find(&nodes); err != nil {
		return nil, err
	}

	log.Warn(len(nodes), nodes)

	// 查询每个节点的审批人
	for _, node := range nodes {
		if err := common.DB.Where("node_id = ?", node.Id).Find(&node.ItemList); err != nil {
			return nil, err
		}
	}
	log.Warn(len(nodes), nodes)
	return nodes, nil
}

func getTaskNodeList(id int64) (*Task, error) {
	t := &Task{
		NodeList: make([]*TaskNode, 0),
	}

	if _, err := common.DB.Where("id = ?", id).Get(t); err != nil {
		return nil, err
	}

	// 查询节点列表
	if err := common.DB.Where("task_id = ?", id).Asc("id").Find(&t.NodeList); err != nil {
		return nil, err
	}

	// 查询批注列表
	if err := common.DB.Where("task_id = ?", id).Asc("user_name").Find(&t.CommentList); err != nil {
		return nil, err
	}

	// 查询每个节点的审批人
	for _, node := range t.NodeList {
		node.ItemList = make([]*TaskNodeItem, 0)
		if err := common.DB.Where("node_id = ?", node.Id).Find(&node.ItemList); err != nil {
			return nil, err
		}
	}
	return t, nil
}
